 1.大数据高速计算引擎Spark(上)之Spark SQL中Spark SQL概述
   
   Hive的诞生，主要是因为开发MapReduce程序对 Java 要求比较高，为了让他们能够
操作HDFS上的数据，推出了Hive。Hive与RDBMS的SQL模型比较类似，容易掌握。Hive的主
要缺陷在于它的底层是基于MapReduce的，执行比较慢。
   
   在Spark 0.x 版的时候推出了Shark，Shark与Hive是紧密关联的，Shark底层很多东
西还是依赖于Hive，修改了内存管理、物理计划、执行三个模块，底层使用Spark的基
于内存的计算模型，性能上比Hive提升了很多倍。
   
   Shark更多是对Hive的改造，替换了Hive的物理执行引擎，提高了执行速度。但Shark
继承了大量的Hive代码，因此给优化和维护带来了大量的麻烦。
   
   在Spark 1.x 的时候Shark被淘汰。在2014 年7月1日的Spark Summit上，Databricks
宣布终止对Shark的开发，将重点放到 Spark SQL 上。
   
   Shark终止以后，产生了两个分支：
       Hive on Spark
   hive社区的，源码在hive中
       Spark SQL（Spark on Hive）
   Spark社区，源码在Spark中，支持多种数据源，多种优化技术，扩展性好很多
   
   Apache Spark 3.0.0 解决超过3400个Jira问题被解决，这些问题在Spark各个核心组
件中分布情况如下图：
 
 2.Spark SQL特点
   
   Spark SQL自从面世以来不仅接过了shark的接力棒，为spark用户提供高性能的SQL
on hadoop的解决方案，还为spark带来了通用的高效的，多元一体的结构化的数据处
理能力。
   Spark SQL的优势：
      写更少的代码
      读更少的数据（SparkSQL的表数据在内存中存储不使用原生态的JVM对象存储
方式，而是采用内存列存储）
      提供更好的性能(字节码生成技术、SQL优化)
   
 3.Spark SQL数据抽象
   
   SparkSQL提供了两个新的抽象，分别是DataFrame和DataSet；
   同样的数据都给到这三个数据结构，经过系统的计算逻辑，都得到相同的结果。不同
是它们的执行效率和执行方式；
   在后期的Spark版本中，DataSet会逐步取代 RDD 和 DataFrame 成为唯一的API接口。
   1).DataFrame
   DataFrame的前身是SchemaRDD。Spark1.3 更名为DataFrame。不继承RDD，自己实现了
RDD的大部分功能。
   与RDD类似，DataFrame也是一个分布式数据集：
      DataFrame可以看做分布式 Row 对象的集合，提供了由列组成的详细模式信息，使
其可以得到优化。DataFrame 不仅有比RDD更多的算子，还可以进行执行计划的优化
      DataFrame更像传统数据库的二维表格，除了数据以外，还记录数据的结构信息，
即schema
      DataFrame也支持嵌套数据类型(struct、array和map)
	  DataFrame API提供的是一套高层的关系操作，比函数式的RDD API要更加友好，
门槛更低
      Dataframe的劣势在于在编译期缺少类型安全检查，导致运行时出错
   2).DataSet
   DataSet是在Spark1.6 中添加的新的接口；
   与RDD相比，保存了更多的描述信息，概念上等同于关系型数据库中的二维表；
   与DataFrame相比，保存了类型信息，是强类型的，提供了编译时类型检查；
   调用Dataset的方法先会生成逻辑计划，然后Spark的优化器进行优化，最终生成物理
计划，然后提交到集群中运行。
   DataSet包含了DataFrame的功能，在Spark2.0 中两者得到了统一：DataFrame表示为
DataSet[Row]，即DataSet的子集。
   3).Row & Schema
   DataFrame = RDD[Row] + Schema；DataFrame 的前身是 SchemaRDD
   Row是一个泛化的无类型 JVM object
import org.apache.spark.sql.Row
val row1 = Row(1,"abc", 1.2)
// Row 的访问方法
row1(0)
row1(1)
row1(2)
row1.getInt(0)
row1.getString(1)
row1.getDouble(2)

row1.getAs[Int](0)
row1.getAs[String](1)
row1.getAs[Double](2)
   DataFrame（即带有Schema信息的RDD），Spark通过Schema就能够读懂数据。
   什么是schema？
   DataFrame中提供了详细的数据结构信息，从而使得SparkSQL可以清楚地知道该数据集
中包含哪些列，每列的名称和类型各是什么，DataFrame中的数据结构信息，即为schema。

import org.apache.spark.sql.types._
val schema = (new StructType).
add("id", "int", false).
add("name", "string", false).
add("height", "double", false)
   参考源码：StructType.scala
// 多种方式定义schema，其核心是StructType
import org.apache.spark.sql.types._
// 来自官方帮助文档
val schema1 = StructType( StructField("name", StringType,false) ::
              StructField("age",  IntegerType,false) ::
              StructField("height", IntegerType,false) ::  Nil)
val schema2 = StructType( Seq(StructField("name", StringType,
false),
               StructField("age",  IntegerType,
false),
               StructField("height",
IntegerType, false)))
val schema3 = StructType( List(StructField("name", StringType,false),
              StructField("age",IntegerType, false),
              StructField("height",IntegerType, false)))

// 来自源码
val schema4 = (new StructType).
add(StructField("name", StringType, false)).
add(StructField("age",  IntegerType, false)).
add(StructField("height", IntegerType, false))

val schema5 = (new StructType).
add("name", StringType, true, "comment1").
add("age", IntegerType, false, "comment2").
add("height", IntegerType, true, "comment3")
   4).三者的共性
   (1)、RDD、DataFrame、Dataset都是 Spark 平台下的分布式弹性数据集，为处理海
量数据提供便利
   (2)、三者都有许多相同的概念，如分区、持久化、容错等；有许多共同的函数，如
map、filter，sortBy等
   (3)、三者都有惰性机制，只有在遇到 Action 算子时，才会开始真正的计算
   (4)、对DataFrame和Dataset进行操作许多操作都需要这个包进行支持， import
spark.implicits._
   5).三者的区别
   DataFrame(DataFrame = RDD[Row] + Schema):
   (1)、与RDD和Dataset不同，DataFrame每一行的类型固定为Row，只有通过解析才能
获取各个字段的值
   (2)、DataFrame与Dataset均支持 SparkSQL 的操作
   
   Dataset(Dataset = RDD[case class].toDS):
   (1)、Dataset和DataFrame拥有完全相同的成员函数，区别只是每一行的数据类型不同；
   (2)、DataFrame 定义为 Dataset[Row]。每一行的类型是Row，每一行究竟有哪些字
段，各个字段又是什么类型都无从得知，只能用前面提到的getAS方法或者模式匹配拿出
特定字段；
   (3)、Dataset每一行的类型都是一个case class，在自定义了case class之后可以很自
由的获得每一行的信息；
 
 4.数据类型
   
   http://spark.apache.org/docs/latest/sql-ref-datatypes.html
   